﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Ccit.SysPlat.Log;
using Ccit.Utils;
using Ccit.ClassLibrary;
using System.Text;
using System.Data;

namespace Ccit.SysPlat.Purview
{
    /// <summary>
    /// Description: 系统平台权限菜单 -> 权限管理SQL SERVER数据实现层
    /// Author: tim 2010-03-11
    /// </summary>
    public class PurviewSQL : IPurview
    {
        #region init error log interface
        private ILog _logInterface = null;
        private const string _funcPageName = "系统权限";
        public PurviewSQL()
        {
            _logInterface = Factory.CreateObject(MsErrLog.assemblyName, MsErrLog.className, 
                                                    ImportComponentType.DotNetDll, null) as ILog;
        }        
        #endregion

        #region IPurview 成员

        public string GetUserPrvMenuIds(string userId, eUserType enUserType, string organId)
        {
            if (string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(organId)) return string.Empty;

            IRole _roleProcessor = Factory.CreateObject(MsRole.assemblyName, MsRole.className, ImportComponentType.DotNetDll, null) as IRole;
            string roleIds = _roleProcessor.GetRoleIdsByUserId(userId,enUserType, organId);

            if (string.IsNullOrEmpty(roleIds)) return string.Empty;

            StringBuilder sbCmdText = new StringBuilder();
            sbCmdText.Append("SELECT PUR_R2_20 AS MENUID FROM PUR_R2 WHERE PUR_R2_10 IN (").Append(roleIds).Append(") ");
            if (enUserType == eUserType.ORDINARY)
            {
                sbCmdText.Append("UNION SELECT PUR_B1_10 AS MENUID FROM PUR_B1 WHERE PUR_B1_50='0' AND PUR_B1_60='0' AND PUR_B1_80='0' ");
                sbCmdText.Append("AND PUR_B1_90='1' AND PUR_B1_100='0' AND PUR_B1_140='0'");
            }

            string prvMenuIds = string.Empty;
            try
            {
                string menuId = string.Empty;
                using (IDataReader iReader = DataAccessor.ExecuteReader(sbCmdText.ToString()))
                {
                    while (iReader.Read())
                    {
                        menuId = iReader["MENUID"].ToString();
                        prvMenuIds += (string.IsNullOrEmpty(prvMenuIds)) ? menuId : "," + menuId;
                    }
                }
            }
            catch (Exception ex)
            {
                MsErrLog msErrorLog = new MsErrLog
                {
                    funcPageName = _funcPageName,
                    errMsg = ex.Message,
                    codeTrack = ex.StackTrace,
                    errClassCode = "001", //SQL 异常
                    paramInfo = "<SQL><![CDATA[" + sbCmdText.ToString() + "]]></SQL>"
                };

                _logInterface.WriteErrorLog(msErrorLog);
                msErrorLog = null;
            }

            sbCmdText = null;
            _roleProcessor = null;
            return prvMenuIds;
        }
        
        public List<MsMenu> GetUserPrvMenuList(string userId, eUserType enUserType, string organId)
        {
            if (string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(organId)) return new List<MsMenu>();

            string prvMenuIds = GetUserPrvMenuIds(userId, enUserType, organId);
            if (string.IsNullOrEmpty(prvMenuIds)) return new List<MsMenu>();

            List<string> lstModMenu = getModMenuIds(prvMenuIds);
            List<MsMenu> lstMenu = new List<MsMenu>();

            int modIndex = 0;
            string modMenuIds = string.Empty;            
            foreach (string eModMenuId in lstModMenu)
            {
                if (modIndex.Equals(0)) getEntireMenus(eModMenuId, ref lstMenu, prvMenuIds); //获取模块菜单下的全部菜单信息
                else
                {
                    //为减少连接数据库次数，其余的模块一起读取
                    modMenuIds += (string.IsNullOrEmpty(modMenuIds)) ? eModMenuId : "," + eModMenuId;
                }
                modIndex++;
            }

            if(!string.IsNullOrEmpty(modMenuIds)) getModMenuInfo(modMenuIds, ref lstMenu);  //仅获取当前模块菜单的信息

            lstModMenu = null;
            return lstMenu;
        }


        public List<MsMenu> GetUserMenusByModId(string modMenuId, string userId, eUserType enUserType, string organId)
        {
            if (string.IsNullOrEmpty(modMenuId) || string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(organId)) return new List<MsMenu>();

            string prvMenuIds = GetUserPrvMenuIds(userId, enUserType, organId);
            if (string.IsNullOrEmpty(prvMenuIds)) return new List<MsMenu>();
                        
            List<MsMenu> lstMenu = new List<MsMenu>();
            getEntireMenus(modMenuId, ref lstMenu, prvMenuIds); //获取模块菜单下的全部菜单信息
            return lstMenu;
        }

        #endregion

        #region private methods

        /// <summary>
        /// 根据叶子节点菜单Id串获取对应的模块菜单Id串
        /// </summary>
        /// <param name="leafMenuIds"></param>
        /// <returns></returns>
        private List<string> getModMenuIds(string leafMenuIds)
        {            
            StringBuilder sbCmdText = new StringBuilder();
            sbCmdText.Append("SELECT PUR_B1_10 AS MENUID FROM PUR_B1 WHERE PUR_B1_30 IN ");
            sbCmdText.Append("(SELECT SUBSTRING(PUR_B1_30,1,6) AS LAYCODE FROM PUR_B1 WHERE PUR_B1_10 IN (" + leafMenuIds + ")) ");
            sbCmdText.Append("AND PUR_B1_50='0' AND PUR_B1_60='0' ORDER BY PUR_B1_40 ASC");

            List<string> lstModMenu = new List<string>();
            try {
                string menuId = string.Empty;
                using (IDataReader iReader = DataAccessor.ExecuteReader(sbCmdText.ToString()))
                {
                    while (iReader.Read())
                    {
                        menuId = iReader["MENUID"].ToString();
                        lstModMenu.Add(menuId);
                    }
                }
            }
            catch (Exception ex)
            {
                MsErrLog msErrorLog = new MsErrLog
                {
                    funcPageName = _funcPageName,
                    errMsg = ex.Message,
                    codeTrack = ex.StackTrace,
                    errClassCode = "001", //SQL 异常
                    paramInfo = "<SQL><![CDATA[" + sbCmdText.ToString() + "]]></SQL>"
                };

                _logInterface.WriteErrorLog(msErrorLog);
                msErrorLog = null;
            }

            lstModMenu = lstModMenu.Distinct().ToList<string>();
            return lstModMenu;
        }


        private void getEntireMenus(string modMenuId, ref List<MsMenu> lstMenu, string prvMenuIds)
        {
            StringBuilder sbCmdText = new StringBuilder();
            sbCmdText.Append("SELECT A.PUR_B1_10 AS MENUID,A.PUR_B1_20 AS MENUNAME,A.PUR_B1_30 AS LAYCODE,A.PUR_B1_90 AS ISLEAF,A.PUR_B1_110 AS PAGEPATH,A.PUR_B1_130 AS IMGPATH,");
            sbCmdText.Append("A.PUR_B1_40 AS ORDERNO FROM PUR_B1 A INNER JOIN (SELECT PUR_B1_30 AS LAYCODE FROM PUR_B1 WHERE PUR_B1_10='").Append(modMenuId).Append("') B ");
            sbCmdText.Append("ON A.PUR_B1_30 LIKE '' + B.LAYCODE + '%' ");
            sbCmdText.Append("WHERE A.PUR_B1_50='0' AND A.PUR_B1_60='0' ORDER BY A.PUR_B1_30 ASC");

            try {
                MsMenu msMenu;
                string menuId = string.Empty;
                int lay = 1;
                string isLeaf = string.Empty;
                StringLib oString = new StringLib(prvMenuIds);
                bool bFilter = false;  //是否需要过滤掉,如果菜单不在用户权限范围内，则为true，需要过滤掉
                using (IDataReader iReader = DataAccessor.ExecuteReader(sbCmdText.ToString()))
                {
                    while (iReader.Read())
                    {
                        bFilter = false;
                        menuId = iReader["MENUID"].ToString();
                        lay = iReader["LAYCODE"].ToString().Length / 6;
                        isLeaf = iReader["ISLEAF"].ToString();
                        if ((lay.Equals(2) && isLeaf.Equals("1")) || lay.Equals(3))  //二级节点并且是叶子节点,或者是三级节点
                        {
                            bFilter = !oString.Contains(menuId);
                        }
                        if (bFilter) continue;

                        msMenu = new MsMenu {
                            menuId = menuId,
                            menuName = iReader["MENUNAME"].ToString(),
                            layCode = iReader["LAYCODE"].ToString(),
                            imgPath = iReader["IMGPATH"].ToString(),
                            orderNo = iReader["ORDERNO"].ToString(),
                            isLeaf = iReader["ISLEAF"].ToString(),
                            pagePath = iReader["PAGEPATH"].ToString(),
                            lay = lay.ToString()
                        };
                        lstMenu.Add(msMenu);
                    }
                }
            }
            catch (Exception ex)
            {
                MsErrLog msErrorLog = new MsErrLog {
                    funcPageName = _funcPageName,
                    errMsg = ex.Message,
                    codeTrack = ex.StackTrace,
                    errClassCode = "001", //SQL 异常
                    paramInfo = "<SQL><![CDATA[" + sbCmdText.ToString() + "]]></SQL>"
                };

                _logInterface.WriteErrorLog(msErrorLog);
                msErrorLog = null;
            }

            #region 需要将集合中的数据重新处理下,如果二级下没有三级则删除二级节点，如果一级下没有二级则删除一级节点

            List<MsMenu> lstDelMenu = new List<MsMenu>();
            IEnumerable<MsMenu> twoQuery = lstMenu.Where(m => m.lay.Equals("2"));
            foreach (MsMenu eTwoMenu in twoQuery)
            {
                if (eTwoMenu.isLeaf.Equals("1")) continue;
                int threeCount = lstMenu.Where(th => th.lay.Equals("3") && th.layCode.Substring(0, 12).Equals(eTwoMenu.layCode))
                                        .Count();

                if(threeCount.Equals(0)) lstDelMenu.Add(eTwoMenu);
            }

            foreach (MsMenu eDelMenu in lstDelMenu)
            {
                lstMenu.Remove(eDelMenu);
            }

            lstDelMenu.Clear();
            IEnumerable<MsMenu> oneQuery = lstMenu.Where(m => m.lay.Equals("1"));
            foreach (MsMenu eOneMenu in oneQuery)
            {
                int twoCount = lstMenu.Where(th => th.lay.Equals("2") && th.layCode.Substring(0, 6).Equals(eOneMenu.layCode))
                                        .Count();
                if(twoCount.Equals(0)) lstDelMenu.Add(eOneMenu);
            }

            foreach (MsMenu eDelMenu in lstDelMenu)
            {
                lstMenu.Remove(eDelMenu);
            }
            #endregion
        }

        private void getModMenuInfo(string modMenuIds, ref List<MsMenu> lstMenu)
        {
            string cmdText = "SELECT PUR_B1_10 AS MENUID,PUR_B1_20 AS MENUNAME,PUR_B1_30 AS LAYCODE,PUR_B1_130 AS IMGPATH,PUR_B1_40 AS ORDERNO ";
            cmdText += "FROM PUR_B1 WHERE PUR_B1_10 IN (" + modMenuIds + ")";

            try {
                MsMenu msMenu;
                using (IDataReader iReader = DataAccessor.ExecuteReader(cmdText))
                {
                    while (iReader.Read())
                    {
                        msMenu = new MsMenu {
                            menuId = iReader["MENUID"].ToString(),
                            menuName = iReader["MENUNAME"].ToString(),
                            layCode = iReader["LAYCODE"].ToString(),
                            imgPath = iReader["IMGPATH"].ToString(),
                            orderNo = iReader["ORDERNO"].ToString(),
                            lay = "1"
                        };
                        lstMenu.Add(msMenu); 
                    }
                }
            }
            catch (Exception ex)
            {
                MsErrLog msErrorLog = new MsErrLog
                {
                    funcPageName = _funcPageName,
                    errMsg = ex.Message,
                    codeTrack = ex.StackTrace,
                    errClassCode = "001", //SQL 异常
                    paramInfo = "<SQL><![CDATA[" + cmdText + "]]></SQL>"
                };

                _logInterface.WriteErrorLog(msErrorLog);
                msErrorLog = null;
            }

        }
        #endregion


    }
}
